import java.util.ArrayList;
import java.util.List;

public class FanTest {

  public static void main(String[] args) {
    // 反推如下
    List<? extends Fruit> list = null;
//    List<? super Apple> list = null;
//    list = getFoods();
//    list.addAll(getFruits());
    // list.addAll(getFoods()); // 此处报错，编译不通过，原因是如果这个通过，那么下面这句话也该通过
    // list.addAll(getFruits()); // 如果这两个都通过，则说明List中含有Food、Fruit两个实例，从而违背了本文第一句话。
    // <? extends Fruit> 同理

    Plate<? extends Fruit> plate = new Plate<Apple>();
//    plate.setT(new Object());// 不能存，能取
    Fruit apple = plate.getT();

    Plate<? super Fruit> plate1 = new Plate<Food>();
//    Food fruit = plate1.getT();// 不能取，能存
    plate1.setT(new Fruit());
    plate1.setT(new Apple());
//    plate1.setT(new Food());
    Object fr = plate1.getT();// 只能取出Object
  }

  static class Plate<T> {
    T t;

    public void setT(T t) {
      this.t = t;
    }

    public T getT() {
      return t;
    }
  }

  static class Food {

  }

  static class Fruit extends Food {

  }

  static class Apple extends Fruit {

  }

  public static ArrayList<Food> getFoods() {
    return new ArrayList<Food>();
  }

  public static ArrayList<Fruit> getFruits() {
    return new ArrayList<Fruit>();
  }
}
